<template>
    <el-drawer :model-value="isDrawerVisible" title="文件详情" direction="rtl" size="50%" @close="handleClose"
        :with-header="true">
        <div v-if="loading" class="loading-container">
            <el-skeleton :rows="10" animated />
        </div>

        <div v-else-if="error" class="error-container">
            <el-alert type="error" :title="error" :closable="false" show-icon />
        </div>

        <div v-else-if="details" class="details-container">
            <!-- 预览区域 -->
            <div class="preview-section">
                <!-- 【修改点 1】: 将 isImage, isVideo, isText 的 v-if 判断，全部绑定到我们新的 previewUrl 计算属性上 -->
                <template v-if="isImage">
                    <el-image :key="previewUrl" :src="previewUrl" fit="contain"
                        style="max-width: 100%; max-height: 400px;" lazy />
                </template>
                <template v-else-if="isVideo">
                    <video :key="previewUrl" :src="previewUrl" controls
                        style="max-width: 100%; max-height: 400px;"></video>
                </template>
                <template v-else-if="isText">
                    <el-card shadow="never" class="text-preview-card">
                        <pre>{{ textContent || '正在加载文本内容...' }}</pre>
                    </el-card>
                </template>
                <template v-else>
                    <el-empty description="该文件类型不支持预览" />
                </template>
            </div>

            <!-- 元数据详情列表 -->
            <el-descriptions :column="1" border class="details-list">
                <el-descriptions-item label="文件名">
                    <span>{{ details.name }}</span>
                    <el-button type="primary" link @click="copyToClipboard(details.name)"
                        class="copy-btn">复制</el-button>
                </el-descriptions-item>

                <el-descriptions-item label="ETag">
                    <span>{{ details.etag }}</span>
                    <el-button type="primary" link @click="copyToClipboard(details.etag)"
                        class="copy-btn">复制</el-button>
                </el-descriptions-item>

                <template v-if="details.bucket_acl === 'private'">
                    <el-descriptions-item label="过期时间 (秒)">
                        <el-input-number v-model="expirationSeconds" :min="1" :max="604800" controls-position="right"
                            @blur="handleExpirationBlur" placeholder="请输入过期时间 (秒)" />
                    </el-descriptions-item>
                    <el-descriptions-item label="使用 HTTPS">
                        <el-switch v-model="useHttps" disabled />
                    </el-descriptions-item>
                </template>

                <el-descriptions-item label="URL">
                    <div class="url-cell-new">
                        <!-- URL 文本部分 -->
                        <span>{{ activeDownloadUrl }}</span>

                        <!-- 纵向排列的操作按钮组 -->
                        <div class="url-actions">
                            <el-button type="primary" link @click="copyToClipboard(activeDownloadUrl)">复制</el-button>
                            <el-button type="primary" link @click="downloadFile">下载</el-button>
                        </div>
                    </div>
                </el-descriptions-item>

                <el-descriptions-item label="类型">
                    <div class="acl-cell">
                        <span> {{ details.content_type }} </span>
                        <el-button type="primary" link class="copy-btn" @click="openMetadataDrawer">设置元数据</el-button>
                    </div>
                </el-descriptions-item>
                <el-descriptions-item label="文件ACL">
                    <div class="acl-cell">
                        <!-- 显示从后端获取的对象ACL -->
                        <span>{{ aclMap[details.object_acl] || '私有' }}</span>
                        <!-- “设置读写权限”按钮 -->
                        <el-button type="primary" link @click="handleSetPermission" class="action-link-btn">
                            设置读写权限
                        </el-button>
                    </div>
                </el-descriptions-item>

                <el-descriptions-item label="存储类型">
                    <span>
                        {{ storageStore.storageClassMap[details.storage_class] || '标准存储' }}
                    </span>
                </el-descriptions-item>

                <el-descriptions-item label="文件大小">{{ details.size_human }} ({{ details.size_bytes }}
                    Bytes)</el-descriptions-item>
                <el-descriptions-item label="最后修改时间">{{ formatDateTime(details.last_modified) }}</el-descriptions-item>
                <el-descriptions-item label="版本ID" v-if="details.version_id">
                    {{ details.version_id }}
                </el-descriptions-item>
            </el-descriptions>

            <!-- 操作按钮 -->
            <div class="action-buttons">

            </div>
        </div>
    </el-drawer>

    <SetObjectMetadataDrawer v-if="metadataDrawerVisible" v-model="metadataDrawerVisible" :bucket-name="bucketName"
        :object-key="objectKey" @success="handleMetadataUpdateSuccess" />

    <SetObjectAclDialog v-if="isSetAclDialogVisible" v-model:visible="isSetAclDialogVisible" :bucket-name="bucketName"
        :object-key="objectKey" @success="onAclSetSuccess" />
</template>

<script setup>
import { ref, watch, computed } from 'vue';
import { ElMessage } from 'element-plus';
import apiClient from '../api'; // 引入我们配置好的 axios 实例
import { useSettingsStore, useStorageStore } from '@/stores';
// import { secureDownloadFile } from '@/utils/downloadHelper'; // 确认导入的是单个文件下载助手
import { secureDownloadItem } from '@/utils/downloadHelper'; // <-- 导入新的统一函数
import SetObjectMetadataDrawer from '@/components/SetObjectMetadataDrawer.vue';
import SetObjectAclDialog from './SetObjectAclDialog.vue'; // 【新增】导入我们之前创建的对话框组件
import { copyToClipboard } from '@/utils/clipboard.js';

// =======================================================
// Props & Emits
// =======================================================
const props = defineProps({
    visible: {
        type: Boolean,
        required: true,
    },
    bucketName: {
        type: String,
        required: true,
    },
    // 我们只接收最关键的文件名即可
    objectKey: {
        type: String,
        default: '',
    },
});

const emit = defineEmits(['update:visible', 'update-success']);


// =======================================================
// State
// =======================================================
const settingsStore = useSettingsStore();
const storageStore = useStorageStore();
const loading = ref(false);
const error = ref(null);
const details = ref(null);
const isSetAclDialogVisible = ref(false);

const textContent = ref('');
const isDrawerVisible = ref(props.visible); // 用于v-model的内部状态
const metadataDrawerVisible = ref(false);

const expirationSeconds = ref(settingsStore.presignedUrlExpiration);
let lastFetchedExpiration = expirationSeconds.value; // 用于判断值是否真的变了
const useHttps = ref(true); // 仅为UI显示
const activeDownloadUrl = ref(''); // 【新增】用于存储和显示的当前有效下载URL

// =======================================================
// Computed Properties for Preview
// =======================================================

// 【修改点 2】: 这是最核心的修改。我们创建一个新的计算属性 `previewUrl`。
// 它会智能判断文件类型，并返回正确的后端预览接口 URL。
const previewUrl = computed(() => {
    if (!props.bucketName || !props.objectKey || !details.value?.content_type) {
        return '';
    }
    const contentType = details.value.content_type.toLowerCase();

    if (isVideo.value) {
        const encodedKeyForPath = props.objectKey.split('/').map(segment => encodeURIComponent(segment)).join('/');
        return `${apiClient.defaults.baseURL}/api/v1/stream-video/${props.bucketName}/${encodedKeyForPath}`;
    }

    if (isImage.value || isText.value) {
        return `${apiClient.defaults.baseURL}/api/v1/preview?bucket_name=${encodeURIComponent(props.bucketName)}&path=${encodeURIComponent(props.objectKey)}`;
    }

    // 其他情况不支持预览
    return '';
});


const aclMap = {
    'private': '私有',
    'public-read': '公共读',
    'public-read-write': '公共读写',
    'authenticated-read': '授权用户读',
    // 阿里云的“继承Bucket”在S3层面通常就是默认的 private
    'inherit': '继承Bucket (私有)'
};

const handleSetPermission = () => {
    isSetAclDialogVisible.value = true;
};

// 当权限设置成功后，重新获取详情以刷新UI
const onAclSetSuccess = () => {
    fetchObjectDetails();
};

const fileExtension = computed(() => {
    if (!details.value || !details.value.name) return '';
    return details.value.name.split('.').pop().toLowerCase();
});

// 【核心修复 B】: 增强类型判断逻辑
const isImage = computed(() => {
    if (!details.value) return false;
    // 优先使用 content_type
    if (details.value.content_type?.startsWith('image/')) return true;
    // 如果是通用类型，则根据扩展名判断
    if (details.value.content_type === 'application/octet-stream') {
        return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'].includes(fileExtension.value);
    }
    return false;
});

const isVideo = computed(() => {
    if (!details.value) return false;
    // 优先使用 content_type
    if (details.value.content_type?.startsWith('video/')) return true;
    // 如果是通用类型，则根据扩展名判断
    if (details.value.content_type === 'application/octet-stream') {
        return ['mp4', 'webm', 'ogg'].includes(fileExtension.value);
    }
    return false;
});

const isText = computed(() => {
    if (!details.value) return false;
    // 优先使用 content_type
    if (details.value.content_type?.startsWith('text/')) return true;
    // 如果是通用类型，则根据扩展名判断
    if (details.value.content_type === 'application/octet-stream') {
        const textTypes = ['txt', 'json', 'xml', 'csv', 'md', 'html', 'css', 'js', 'py', 'log'];
        return textTypes.includes(fileExtension.value);
    }
    return false;
});



// =======================================================
// Methods
// =======================================================
const handleClose = () => {
    emit('update:visible', false);
};

const formatDateTime = (isoString) => {
    if (!isoString) return 'N/A';
    try {
        return new Date(isoString).toLocaleString();
    } catch (e) {
        return isoString;
    }
};

const downloadFile = () => {
    const item = {
        name: props.objectKey,
        type: 'file',
    };
    secureDownloadItem(props.bucketName, item, expirationSeconds.value);
};

const openMetadataDrawer = () => {
    console.log('设置元数据按钮被点击了！准备打开抽屉...');
    metadataDrawerVisible.value = true;
};

const handleMetadataUpdateSuccess = () => {
    fetchObjectDetails(); // 刷新当前抽屉内容
    emit('update-success'); // 通知父组件（文件列表）也刷新
};

const generateAndDisplayUrl = async (expSeconds) => {
    activeDownloadUrl.value = '正在生成链接...';
    try {
        const response = await apiClient.post('/api/v1/generate-download-link', {
            bucket_name: props.bucketName,
            item: {
                name: props.objectKey,
                type: 'file'
            },
            expires_in: expSeconds,
        });
        const relativeUrl = response.data.download_url;
        if (relativeUrl) {
            activeDownloadUrl.value = `${apiClient.defaults.baseURL}${relativeUrl}`;
        } else {
            throw new Error('Backend did not return a URL');
        }
    } catch (error) {
        activeDownloadUrl.value = '生成下载链接失败';
        console.error("URL generation failed:", error);
    }
};

async function fetchObjectDetails() {
    if (!props.objectKey) return;
    loading.value = true;
    error.value = null;
    details.value = null;
    activeDownloadUrl.value = '正在生成链接...';

    try {
        const response = await apiClient.get(`/api/v1/buckets/${props.bucketName}/objects/details`, {
            params: { key: props.objectKey },
        });
        details.value = response.data;

        await generateAndDisplayUrl(expirationSeconds.value);

        // 【修改点 4】: 当判断为文本时，使用新的 previewUrl 去获取内容
        if (isText.value) {
            fetchTextContent();
        }
    } catch (err) {
        error.value = err.response?.data?.error || '加载文件详情失败';
        activeDownloadUrl.value = '获取信息失败';
    } finally {
        loading.value = false;
    }
}

async function fetchTextContent() {
    // 【修改点 A】: 从参数接收 url 改为直接从 previewUrl 计算属性获取
    const url = previewUrl.value;
    if (!url) return;

    textContent.value = '正在加载文本内容...';
    try {
        // 【核心修复】: 使用 apiClient (axios) 发送请求，它会自动携带认证 cookie
        const response = await apiClient.get(url, {
            // 告诉 axios 期望接收的是纯文本，而不是 JSON
            responseType: 'text'
        });
        textContent.value = response.data;
    } catch (err) {
        // 【修改点 B】: 错误处理现在可以更精确
        const status = err.response?.status;
        console.error(`Failed to fetch text content: ${status}`, err);
        if (status === 401) {
            textContent.value = '加载失败：会话可能已过期，请尝试重新登录。';
        } else {
            textContent.value = '加载文本内容失败。';
        }
    }
}

const handleExpirationBlur = () => {
    if (expirationSeconds.value !== lastFetchedExpiration) {
        settingsStore.setPresignedUrlExpiration(expirationSeconds.value);
        lastFetchedExpiration = expirationSeconds.value;
        if (details.value?.bucket_acl === 'private') {
            activeDownloadUrl.value = '正在更新链接...';
            generateAndDisplayUrl(expirationSeconds.value);
        }
    }
};

// =======================================================
// Watcher
// =======================================================
watch(
    () => props.visible,
    (newVisible) => {
        isDrawerVisible.value = newVisible;
        if (newVisible && props.objectKey) {
            expirationSeconds.value = settingsStore.presignedUrlExpiration;
            lastFetchedExpiration = expirationSeconds.value;
            fetchObjectDetails();
        }
    }
);

</script>

<style scoped>
.loading-container,
.error-container {
    padding: 20px;
}

.details-container {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.preview-section {
    flex-shrink: 0;
    margin-bottom: 20px;
    padding: 10px;
    border: 1px solid var(--el-border-color-lighter);
    border-radius: 4px;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 150px;
    background-color: #f7f7f7;
}

.text-preview-card {
    width: 100%;
}

.text-preview-card pre {
    white-space: pre-wrap;
    word-break: break-all;
    max-height: 400px;
    overflow-y: auto;
}

.details-list {
    margin-bottom: 20px;
}

.details-list :deep(.el-descriptions__label) {
    /* 将标签列的宽度从默认值增加到 120px */
    width: 80px;
}

.copy-btn {
    margin-left: 10px;
}

.url-cell-new {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    word-break: break-all;
    /* 顶部对齐，以防URL换行 */
    width: 100%;
    gap: 16px;
    /* 在URL文本和按钮组之间创建间距 */
}

.url-text {
    /* 允许URL文本换行，并占用尽可能多的空间 */
    word-break: break-all;
    flex-grow: 1;
}

.url-actions {
    /* 核心：让内部的按钮纵向排列 */
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    /* 按钮靠右对齐 */
    flex-shrink: 0;
    /* 防止按钮组被压缩 */
    gap: 8px;
    /* 在“复制”和“下载”按钮之间创建 8px 的垂直间距 */
}

.action-buttons {
    margin-top: auto;
    /* 将按钮推到底部 */
    padding-top: 20px;
    border-top: 1px solid var(--el-border-color-lighter);
    display: flex;
    gap: 10px;
}

.acl-cell {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
}

.action-link-btn {
    /* 模仿阿里云的链接按钮样式 */
    font-size: 14px;
    padding: 0;
    height: auto;
}

.url-actions .el-button {
    /* 移除 Element Plus 按钮默认的左右 margin，让对齐更精确 */
    margin-left: 0;
}
</style>